package net.csdn.business.mirror.pop.service.thirdapi.impl;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import net.csdn.business.common.enums.ResultCodeEnum;
import net.csdn.business.common.exception.BusinessException;
import net.csdn.business.mirror.pop.bo.UserBO;
import net.csdn.business.mirror.pop.dto.MyGithubDto;
import net.csdn.business.mirror.pop.service.thirdapi.ThirdGitApi;
import net.csdn.business.mirror.pop.vo.UserTokenVo;
import net.csdn.business.mirror.utils.HttpUtil;
import net.csdn.business.mirror.utils.StringUtil;
import net.csdn.business.mirror.utils.UrlUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service
@Slf4j
public class ThirdGitCodeGitApiImpl implements ThirdGitApi {

    /**
     * 根据token获取授权用户的资料
     */
    @Value("${gitCodeApi.userUrl:https://api.gitcode.com/api/v5/user}")
    private String userUrl;

    /**
     * 列出授权用户的所有仓库
     */
    @Value("${gitCodeApi.userAllReposUrl:https://api.gitcode.com/api/v5/user/repos}")
    private String userAllReposUrl;

    /**
     * 列出授权用户所属的组织
     */
    @Value("${gitCodeApi.userAllOrgsUrl:https://api.gitcode.com/api/v5/users/orgs}")
    private String userAllOrgsUrl;

    /**
     * 应用通过 浏览器 或 Webview 将用户引导到码云三方认证页面上
     */
    @Value("${gitCodeApi.authorize:https://gitcode.com/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type=code}")
    private String authorizeUrl;


    /**
     * 根据code获取access_token
     */
    @Value("${gitCodeApi.token:https://gitcode.com/oauth/token?grant_type=authorization_code&code={code}&client_id={client_id}&redirect_uri={redirect_uri}&client_secret={client_secret}}")
    private String tokenUrl;

    @Value("${gitCodeApi.client_id:204513d5d8074a86b658621b876aadfd}")
    private String client_id;

    @Value("${gitCodeApi.client_secret:702ee289d06e48449e68847005223e44}")
    private String client_secret;

    @Value("${gitCodeApi.redirect_uri:https://test.atomgit.com/-/others/import/callback}")
    private String redirect_uri;


    @Override
    public UserBO getUser(String token) {
        if (StringUtils.isEmpty(token)) {
            return null;
        }
        Map<String, String> headers = new HashMap<>();
        headers.put("Accept", "application/json;charset=UTF-8");

        Map<String, String> params = new HashMap<>();
        params.put("access_token", token);
        String url = UrlUtil.getNewUrl(userUrl, params);
        String content = HttpUtil.httpRequest(HttpUtil.RequestMethodEnum.GET, url, headers, null, null).getContent();
        UserBO user = JSONUtil.toBean(content, UserBO.class);
        if (Objects.isNull(user) || StringUtils.isEmpty(user.getLogin())) {
            log.error("giteeApi getUser failed: {}", content);
            return null;
        }
        return user;
    }

    @Override
    public void listUserAllRepos(MyGithubDto myGithub, Integer page, Integer pageSize) {
        if (StringUtils.isEmpty(myGithub.getToken())) {
            return;
        }
        if (Objects.isNull(page) || page < 1) {
            page = 1;
        }
        if (Objects.isNull(pageSize) || pageSize < 1 || pageSize > 100) {
            pageSize = 100;
        }

        Map<String, String> headers = new HashMap<>();
        headers.put("Accept", "application/json;charset=UTF-8");

        Map<String, String> params = new HashMap<>();
        params.put("access_token", myGithub.getToken());
        params.put("visibility", "public");
        params.put("affiliation", "admin");
        params.put("sort", "full_name");
        params.put("direction", "asc");
        params.put("page", page.toString());
        params.put("per_page", pageSize.toString());
        String url = UrlUtil.getNewUrl(userAllReposUrl, params);

        HttpUtil.Response response = HttpUtil.httpRequest(HttpUtil.RequestMethodEnum.GET, url, headers, null, null, 10000);
        String content = response.getContent();
        int code = response.getCode();
        if (code != 200) {
            switch (code) {
                case 401:
                case 403:
                    log.error("giteeApi listUserAllRepos token 无效: {}", content);
                    throw new BusinessException(ResultCodeEnum.MIRROR_GITHUB_TOKEN_INVALID);
                default:
                    log.error("giteeApi listUserAllRepos failed reason: {}", content);
                    break;
            }
            return;
        }
        List<net.csdn.business.mirror.pop.dto.MyGithubDto.Repository> repos = JSONUtil.toList(content, net.csdn.business.mirror.pop.dto.MyGithubDto.Repository.class);
        repos.forEach(repo -> {
            String tml_url = repo.getHtml_url();
            String web_url = repo.getWeb_url();
            if (StringUtils.isEmpty(tml_url)) {
                repo.setHtml_url(web_url);
            }
            if (StringUtils.isEmpty(web_url)) {
                repo.setWeb_url(tml_url);
            }
        });
        myGithub.setItems(repos);
        myGithub.setThirdTotalPage(Integer.parseInt(response.getHeaders().getOrDefault("total_page", "0")));
        myGithub.setTotalCount(Integer.parseInt(response.getHeaders().getOrDefault("total_count", String.valueOf(myGithub.getThirdTotalPage()*pageSize))));
    }

    @Override
    public void listUserAllOrgs(net.csdn.business.mirror.pop.dto.MyGithubDto myGithub, Integer page, Integer pageSize) {
        if (StringUtils.isEmpty(myGithub.getToken())) {
            return;
        }
        if (Objects.isNull(page) || page < 1) {
            page = 1;
        }
        if (Objects.isNull(pageSize) || pageSize < 1 || pageSize > 100) {
            pageSize = 100;
        }

        Map<String, String> headers = new HashMap<>();
        headers.put("Accept", "application/json;charset=UTF-8");

        Map<String, String> params = new HashMap<>();
        params.put("access_token", myGithub.getToken());
        params.put("admin", "true");
        params.put("page", page.toString());
        params.put("per_page", pageSize.toString());
        String url = UrlUtil.getNewUrl(userAllOrgsUrl, params);

        HttpUtil.Response response = HttpUtil.httpRequest(HttpUtil.RequestMethodEnum.GET, url, headers, null, null, 10000);
        String content = response.getContent();
        int code = response.getCode();
        if (code != 200) {
            switch (code) {
                case 401:
                case 403:
                    log.error("giteeApi listUserAllOrgs token 无效: {}", content);
                    throw new BusinessException(ResultCodeEnum.MIRROR_GITHUB_TOKEN_INVALID);
                default:
                    log.error("giteeApi listUserAllOrgs failed reason: {}", content);
                    break;
            }
            return;
        }
        List<MyGithubDto.Organization> organizations = JSONUtil.toList(content, MyGithubDto.Organization.class);
//        repos.forEach(repo -> {
//            String[] arr = repo.getFullName().split("/");
//            repo.setName(arr[arr.length - 1]);
//        });
        myGithub.setOrganizations(organizations);
        myGithub.setThirdTotalPage(Integer.parseInt(response.getHeaders().getOrDefault("total_page", "0")));
        myGithub.setTotalCount(Integer.parseInt(response.getHeaders().getOrDefault("total_count", String.valueOf(myGithub.getThirdTotalPage()*pageSize))));
    }

    @Override
    public String authorize() {
        Map<String, Object> parameter = new HashMap<>();
        parameter.put("client_id", client_id);
        parameter.put("redirect_uri", redirect_uri);
        return StringUtil.replace(authorizeUrl, parameter);
    }

    @Override
    public UserTokenVo getToken(String code) {
        Map<String, Object> parameter = new HashMap<>();
        parameter.put("code", code);
        parameter.put("client_id", client_id);
        parameter.put("redirect_uri", redirect_uri);
        parameter.put("client_secret", client_secret);
        String url = StringUtil.replace(tokenUrl, parameter);

        Map<String, String> headers = new HashMap<>();
        headers.put("Accept", "application/json;charset=UTF-8");
        try {
            HttpUtil.Response response = HttpUtil.httpRequest(HttpUtil.RequestMethodEnum.POST, url, headers, null, null, 10000);
            String content = response.getContent();
            UserTokenVo userTokenVo = JSONUtil.toBean(content, UserTokenVo.class);
            return userTokenVo;
        } catch (Exception e) {
            log.error("giteeApi getToken error: ", e);
            return null;
        }
    }
}
